﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Caching;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TfsGiggle.Core.IntegrationTest
{
    /// <summary>
    ///This is a test class for JobManagerIntegrationTest and is intended
    ///to contain all JobManagerIntegrationTest Unit Tests
    ///</summary>
    [TestClass()]
    public class JobManagerIntegrationTest
    {
        private TestContext testContextInstance;
        private static string _temporaryDir;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {
            // Avoid having to create the index for each test
            var cancelToken = new CancellationToken();
            var tfsConfigurationServer = MockTfsConfigurationServerFactory.GetConfigurationServer(new Uri("http://localhost:8080/tfs"));
            _temporaryDir = Path.Combine(Path.GetTempPath() + "TfsGiggle", Path.GetRandomFileName());
            JobManager.Instance.Open(_temporaryDir, tfsConfigurationServer, cancelToken);
        }

        [ClassCleanup()]
        public static void MyClassCleanup()
        {
            JobManager.Instance.Dispose();
            Directory.Delete(_temporaryDir, true);
        }
        #endregion


        /// <summary>
        /// Find stuff
        ///</summary>
        [TestMethod()]
        public void Query_Must_Return_Results_For_XYZ()
        {
            // See MyClassInitialize for initialization
            const string SearchForThisString = "xyz";
            var mockChangeset = new MockChangeset().
                MockAddFile("Query_Must_Return_Results_For_XYZ.cs", "using System;private void test1(){}").
                MockAddFile("Query_Must_Return_Results_For.cpp", "include <stdio.h> void main() { stdout >> " + SearchForThisString + " ;}").
                MockId(1);
            MemoryCache.Default["changeset"] = mockChangeset;
            int currentNumberOfDocuments = JobManager.Instance.IndexModel.NumberOfDocuments;
            JobManager.Instance.AddJob(new Guid().ToString(), mockChangeset.ChangesetId);
            var timer = new Stopwatch();
            timer.Start();
            int MaxWaitInSeconds = Debugger.IsAttached ? (int)TimeSpan.FromHours(1).TotalSeconds : 5;
            while (JobManager.Instance.IndexModel.NumberOfDocuments <= currentNumberOfDocuments)
            {
                Thread.Sleep(200);
                if (timer.ElapsedMilliseconds > TimeSpan.FromSeconds(MaxWaitInSeconds).TotalMilliseconds)
                {
                    Assert.IsTrue(false, "We hit the timeout");
                    break;
                }
            }
            timer.Stop();
            Debug.WriteLine("Waited {0} ticks", timer.ElapsedTicks);
            Assert.AreEqual<int>(JobManager.Instance.IndexModel.NumberOfDocuments, currentNumberOfDocuments + mockChangeset.Changes.Length, "Document(s) must have been added to the index");
            var result = JobManager.Instance.IndexModel.Query(SearchForThisString);
            Assert.IsTrue(result != null && result.Files != null && result.Files.Length > 0, "There must be files");
        }

        /// <summary>
        /// Find stuff
        /// </summary>
        [TestMethod()]
        public void MustFindIndexedMethod()
        {
            var methodToFind = string.Format("TestMethod{0}_Test", new Random().Next(200, 1000));
            var mockChangeset = new MockChangeset().
                MockAddFile("Test1.cs", "using System;namespace TfsGiggle.Core.IntegrationTest{class Class1{void " + methodToFind + "() { Console.WriteLine(this.ToString()); }}}");
            MemoryCache.Default["changeset"] = mockChangeset;
            int currentNumberOfDocuments = JobManager.Instance.IndexModel.NumberOfDocuments;
            JobManager.Instance.AddJob(new Guid().ToString(), mockChangeset.ChangesetId);
            var timer = new Stopwatch();
            timer.Start();
            int MaxWaitInSeconds = Debugger.IsAttached ? (int)TimeSpan.FromHours(1).TotalSeconds : 5;
            while (JobManager.Instance.IndexModel.NumberOfDocuments <= currentNumberOfDocuments)
            {
                Thread.Sleep(200);
                if (timer.ElapsedMilliseconds > TimeSpan.FromSeconds(MaxWaitInSeconds).TotalMilliseconds)
                {
                    Assert.IsTrue(false, "We hit the timeout");
                }
            }
            timer.Stop();
            Debug.WriteLine("Waited {0} ticks", timer.ElapsedTicks);
            var result = JobManager.Instance.IndexModel.Query("method:" + methodToFind);
            Assert.IsTrue(result != null && result.Files != null && result.Files.Length > 0, "There must be files");
        }

        /// <summary>
        /// Find stuff
        /// </summary>
        [TestMethod()]
        public void Query_Must_Find_ChangesetId()
        {
            int changesetId = new Random().Next(200, 1000);
            var mockChangeset = new MockChangeset().
                MockAddFile("Query_Must_Find_ChangesetId.cs", "using System;private void Query_Must_Find_ChangesetId(){}").
                MockId(changesetId);
            MemoryCache.Default["changeset"] = mockChangeset;
            int currentNumberOfDocuments = JobManager.Instance.IndexModel.NumberOfDocuments;
            JobManager.Instance.AddJob(new Guid().ToString(), mockChangeset.ChangesetId);
            var timer = new Stopwatch();
            timer.Start();
            const int MaxWaitInSeconds = 5;
            while (JobManager.Instance.IndexModel.NumberOfDocuments <= currentNumberOfDocuments)
            {
                Thread.Sleep(200);
                if (timer.ElapsedMilliseconds > TimeSpan.FromSeconds(MaxWaitInSeconds).TotalMilliseconds)
                {
                    Assert.IsTrue(false, "We hit the timeout");
                }
            }
            timer.Stop();
            Debug.WriteLine("Waited {0} ticks", timer.ElapsedTicks);
            Assert.AreEqual<int>(JobManager.Instance.IndexModel.NumberOfDocuments, currentNumberOfDocuments + mockChangeset.Changes.Length, "A document must have been added to the index");
            var result = JobManager.Instance.IndexModel.Query(changesetId.ToString());
            Assert.IsTrue(result != null && result.Files != null && result.Files.Length > 0, "There must be files");
            result = JobManager.Instance.IndexModel.Query("34508129");
            Assert.IsTrue(result.Files.Length == 0, "No result must be found for this changesetid");
            result = JobManager.Instance.IndexModel.Query("Query_Must_Find_ChangesetId");
            Assert.IsTrue(result != null && result.Files != null && result.Files.Length > 0, "There must be files");
        }

    }
}